﻿#include "FloatingActivator.h"
#include "ui_FloatingActivator.h"

#include <QBitmap>
#include <QPainter>
#include <QMouseEvent>
#include <QGuiApplication>
#include <QScreen>
#include <QPropertyAnimation>
#include <QDebug>

// 悬浮球大小
#define FIXED_SIZE QSize(100, 100)
// 停靠后剩余的可见范围
#define REMAIN_SPACE 20
// 触发停靠效果的范围
#define SENSITIVE_SPACE 20

FloatingActivator::FloatingActivator(QWidget* parent) :
    QWidget(parent, Qt::FramelessWindowHint)
{
	setAttribute(Qt::WA_TranslucentBackground);

	// 加载背景图
	m_pixmap = new QPixmap();
	m_pixmap->load("://assets/ball1.png");
	*m_pixmap = m_pixmap->scaled(FIXED_SIZE, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);

	// 重设窗体大小
	resize(FIXED_SIZE);

	// 移动到主屏幕右下角
    QRect rect = QGuiApplication::primaryScreen()->availableGeometry();
    move(rect.width() - width() - 50, rect.height() - height() - 50);
	m_screenWidth = rect.width();
}

FloatingActivator::~FloatingActivator()
{
	delete m_pixmap;
}

void FloatingActivator::paintEvent(QPaintEvent*)
{
	// 绘制出背景
	QPainter painter(this);
	painter.drawPixmap(0, 0, *m_pixmap);
}

void FloatingActivator::mousePressEvent(QMouseEvent* e)
{
	//按住左键可以拖动窗口
	if (e->button() == Qt::LeftButton)
	{
		m_lastPoint = e->globalPos() - frameGeometry().topLeft();
		e->accept();

		setCursor(Qt::ClosedHandCursor);

        m_pressedTime = QDateTime::currentDateTime();
	}
}

void FloatingActivator::mouseMoveEvent(QMouseEvent* e)
{
	// 随鼠标左键拖动而移动，在屏幕边缘了，则进行贴边
    if (e->buttons() & Qt::LeftButton)
	{
		move(e->globalPos() - m_lastPoint);

		if (y() < SENSITIVE_SPACE)
		{
			m_direction = Direction::Up;
			move(x(), 0);
		}
		else if (x() < SENSITIVE_SPACE)
		{
			m_direction = Direction::Left;
			move(0, y());
		}
		else if (x() > (m_screenWidth - width() - SENSITIVE_SPACE))
		{
			m_direction = Direction::Right;
			move(m_screenWidth - width(), y());
		}

		e->accept();
	}
}

void FloatingActivator::mouseReleaseEvent(QMouseEvent*)
{
	setCursor(Qt::OpenHandCursor);

    // 200毫秒内释放鼠标，认为是用户单击，则发出点击事件
    QDateTime now = QDateTime::currentDateTime();
    if (now.toMSecsSinceEpoch() - m_pressedTime.toMSecsSinceEpoch() < 200)
	{
		emit clicked();
	}
}

void FloatingActivator::enterEvent(QEvent*)
{
	if (m_isDocked)
	{
		popupWidget();
	}

	setCursor(Qt::OpenHandCursor);
}

void FloatingActivator::leaveEvent(QEvent*)
{
	bool shouldDock = false;
	if (m_direction == Direction::Up)
	{
		shouldDock = (y() <= 0);
	}
	else if (m_direction == Direction::Left)
	{
		shouldDock = (x() <= 0);
	}
	else if (m_direction == Direction::Right)
	{
		shouldDock = (x() >= (m_screenWidth - width()));
	}
	if (shouldDock)
	{
		dockWidget();
		m_isDocked = true;
	}
	else
	{
		m_isDocked = false;
	}

	setCursor(Qt::ArrowCursor);
}

void FloatingActivator::dockWidget()
{
	QPoint startPos = pos();
	QPoint endPos;
	if (m_direction == Direction::Up)
	{
        endPos = QPoint(x(), -height() + REMAIN_SPACE);
	}
	else if (m_direction == Direction::Left)
	{
        endPos = QPoint(-width() + REMAIN_SPACE, y());
	}
	else if (m_direction == Direction::Right)
	{
        endPos = QPoint(m_screenWidth - REMAIN_SPACE, y());
	}

	if (startPos == endPos)
	{
		return;
	}

	QPropertyAnimation* animation = new QPropertyAnimation(this, "pos", this);
	// 取消置顶
//	connect(animation, &QAbstractAnimation::finished, [this]()
//	{
//		setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
//		show();
//	});

	animation->setDuration(200);
	animation->setStartValue(startPos);
	animation->setEndValue(endPos);
	animation->setEasingCurve(QEasingCurve::InQuad);
	animation->start(QAbstractAnimation::DeleteWhenStopped);
}

void FloatingActivator::popupWidget()
{
	QPoint startPos = pos();
	QPoint endPos;
	if (m_direction == Direction::Up)
	{
		endPos = QPoint(x(), 0);
	}
	else if (m_direction == Direction::Left)
	{
		endPos = QPoint(0, y());
	}
	else if (m_direction == Direction::Right)
	{
		endPos = QPoint(m_screenWidth - width(), y());
	}

	if (startPos == endPos)
	{
		return;
	}

	// 置顶窗口
//	setWindowFlags(windowFlags() & ~Qt::WindowStaysOnTopHint);
//	show();

	QPropertyAnimation* animation = new QPropertyAnimation(this, "pos", this);
	animation->setDuration(200);
	animation->setStartValue(startPos);
	animation->setEndValue(endPos);
	animation->setEasingCurve(QEasingCurve::OutQuad);
	animation->start(QAbstractAnimation::DeleteWhenStopped);
}
